home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------------
-
- smtp.c
-
- This reusable and reentrant module implements SMTP mail.
-
- The following functions are exported:
-
- SmtpOpen - Open an SMTP stream.
- SmtpClose - Close an SMTP stream.
- SmtpSendMessage - Send a mail message.
- SmtpGetServerErrInfo - Get server error information.
-
- You must call memutil.c/InitMemUtil and net.c/NetInit before calling any of
- the functions in this module. You also must call the NetIdle function in your
- idle loop, and the NetTerm function at program termination.
-
- A "stream" is an abstraction representing a bidirectional network connection
- to an SMTP server. A stream is represented as a variable of type "SmtpStreamRef".
- These stream references are opaque. You may copy them and pass them as parameters
- to functions in smtp.c, but you are prohibited from accessing the contents of
- the memory blocks pointed to by the references. Only the functions in
- smtp.c are permitted to manipulate the contents of these blocks.
-
- The functions return a value of type OSErr as the function result:
-
- noErr no error occurred
- smtpServerErr server error
- other any other OS or Toolbox error code
-
- If the function result is smtpServerErr, the SmtpGetServerErrInfo function can
- be called to get information about the server error. On server errors, the
- stream is still allocated and open on return to the caller.
-
- If an OS or Toolbox error occurs, the stream is aborted and deallocated before
- returning to the caller. "Aborted" means that the server connection is closed
- abruptly, without going through the usual TCP stream teardown process. You must
- perform careful error checking. The stream is deallocated, and must not be reused.
-
- Copyright © 1994-1995, Northwestern University.
-
- ----------------------------------------------------------------------------*/
-
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-
- #include "def.h"
- #include "net.h"
- #include "smtp.h"
- #include "memutil.h"
-
-
-
- /* Types. */
-
- typedef struct TStream {
- NetStreamRef netStream; /* net stream reference */
- Boolean needReset; /* true if must send RSET command before
- next message */
- } TStream, *TStreamPtr, **TStreamHandle;
-
-
-
- /*----------------------------------------------------------------------------
- SmtpOpen
-
- Open an SMTP stream.
-
- Entry: host = server host address (domain name or dotted
- decimal IP address).
-
- Exit: function result = result code.
- stream = reference to opened stream,
- or nil if function result != noErr.
- ----------------------------------------------------------------------------*/
-
- OSErr SmtpOpen (char *host, SmtpStreamRef *stream)
- {
- TStreamHandle s = nil;
- unsigned long addr;
- unsigned short port;
- NetStreamRef netStream;
- CStr255 myName;
- CStr255 command, response;
- long responseCode;
- OSErr err = noErr;
-
- err = MyNewHandle(sizeof(TStream), &s);
- if (err != noErr) return err;
-
- err = NetNameToAddr(host, kSMTPPort, &addr, &port);
- if (err != noErr) goto exit;
-
- err = NetOpen(addr, port, true, &netStream, &responseCode, response);
- if (err != noErr) goto exit;
-
- (**s).netStream = netStream;
- (**s).needReset = false;
- *stream = (SmtpStreamRef)s;
-
- if (responseCode != 220) return smtpServerErr;
-
- err = NetGetMyName(myName);
- if (err != noErr) {
- err = NetGetMyAddrStr(myName);
- if (err != noErr) {
- NetClose(netStream);
- goto exit;
- }
- }
- sprintf(command, "HELO %.250s", myName);
- err = NetCommand(netStream, command, &responseCode, response);
- if (err != noErr) goto exit;
- if (responseCode != 250) return smtpServerErr;
-
- return noErr;
-
- exit:
-
- MyDisposeHandle(s);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- SmtpClose
-
- Close an SMTP stream.
-
- Entry: stream = stream reference.
-
- Exit: function result = result code.
- ----------------------------------------------------------------------------*/
-
- OSErr SmtpClose (SmtpStreamRef stream)
- {
- TStreamHandle s;
- OSErr err = noErr;
-
- s = (TStreamHandle)stream;
- err = NetClose((**s).netStream);
- MyDisposeHandle(s);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- SmtpSendMessage
-
- Send a mail message.
-
- Entry: stream = stream reference.
- from = C-format email address of sender.
- to = C-format email address of recipient.
- text = handle to message text, including SMTP header, with CR line
- terminators. Warning: the memory block is modified by the function.
- The memory block must be unlocked and nonpurgeable.
-
- Exit: function result = result code.
-
- Multiple recipients may be listed in the "to" string, separated by commas.
- ----------------------------------------------------------------------------*/
-
- OSErr SmtpSendMessage (SmtpStreamRef stream, char *from, char *to, Handle text)
- {
- TStreamHandle s;
- NetStreamRef netStream;
- char *p, *q;
- short len;
- CStr255 command, response;
- long responseCode;
- OSErr err = noErr;
-
- s = (TStreamHandle)stream;
- netStream = (**s).netStream;
-
- if ((**s).needReset) {
- strcpy(command, "RSET");
- err = NetCommand(netStream, command, &responseCode, response);
- if (err != noErr) goto exit1;
- if (responseCode != 250) goto exit2;
- (**s).needReset = false;
- }
-
- sprintf(command, "MAIL FROM:<%.243s>", from);
- err = NetCommand(netStream, command, &responseCode, response);
- if (err != noErr) goto exit1;
- if (responseCode != 250) goto exit2;
-
- p = to;
- while (*p != 0) {
- q = p;
- while (*q != 0 && *q != ',') q++;
- len = q-p;
- if (len > 0 && len <= 245) {
- sprintf(command, "RCPT TO:<%.*s>", len, p);
- err = NetCommand(netStream, command, &responseCode, response);
- if (err != noErr) goto exit1;
- if (responseCode != 250 && responseCode != 251) goto exit2;
- }
- p = q;
- if (*p == ',') p++;
- }
-
- strcpy(command, "DATA");
- err = NetCommand(netStream, command, &responseCode, response);
- if (err != noErr) goto exit1;
- if (responseCode != 354) goto exit2;
-
- err = NetPutText(netStream, text);
- if (err != noErr) goto exit1;
-
- err = NetGetExtraResponse(netStream, &responseCode, response);
- if (err != noErr) goto exit1;
- if (responseCode != 250 && responseCode != 251) goto exit2;
-
- return noErr;
-
- exit1:
-
- MyDisposeHandle(s);
- return err;
-
- exit2:
-
- (**s).needReset = true;
- return smtpServerErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- SmtpGetServerErrInfo
-
- Get server error information.
-
- Entry: stream = stream reference.
-
- Exit: *serverErrInfo = server error information.
- ----------------------------------------------------------------------------*/
-
- void SmtpGetServerErrInfo (SmtpStreamRef stream, NetServerErrInfo *serverErrInfo)
- {
- TStreamHandle s;
-
- s = (TStreamHandle)stream;
- NetGetServerErrInfo((**s).netStream, serverErrInfo);
- }
-